{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true,
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "# 训练音乐推荐系统\n",
    "\n",
    "基于现有的 Word2vec 模型。\n",
    "\n",
    "把每张播放列表中的曲目 id 和在一起，作为一个个的句子，喂给 w2v：\n",
    "\n",
    "```py\n",
    "sentences = [\n",
    "    [\"track_1_id\", \"track_2_id\", ...], # playlist_1\n",
    "    [...], # playlist_2\n",
    "    ...\n",
    "]\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "39 ['01apQz7E72krU1k1b4VWs7', '0I4GET1to4HFDGOD7C2yZq', '0KDn1sQyUdgD4X1LYlEbTe', '0gthY07uquYTZXfg1Kc5EX', '0nHQAxZgzAcKGRxAsOISTc', '0trTpNYmHAK3EihaZBd2h6', '0uxPr0jgZcSu2E2CbazF1q', '180MVaidIYWpB1MSYEv5BI', '1EbUvGMGNtR5VoJOXDwgm6', '1LGv7Ah6TXp1soAAIzzuGC', '1k6GEdfONk9Fs6JgrC8aBN', '2FppDwkXcO6AveFobwZGS0', '2QnRyMZ7nCQdopDlwef4lm', '2mqOYFXvkB2N9B4zDKHlgA', '2q4PnncxGIm1oVQzu6hS2d', '2yD6IiTv51oeFY3pC4cOLj', '41L3O37CECZt3N7ziG2z7l', '4DG4um6R0wx4WrqhhACc5g', '4Xn2RsLiDUDisOgJ24FigK', '4bw49rU057FSUTpGF4pnxq', '50bWipKseUhTCP5YPiGRbA', '55hbMmAsueVEBTdwbv3TiF', '57G7JxlRQ40mdLFKjI8PWo', '5HAdd9vei9veddPVJXcG7F', '5NF2n5zIR3t2P6p44ieyI8', '5Ush5YElzq1zjldlllP7hp', '5ZrDlcxIDZyjOzHdYW1ydr', '5ygDXis42ncn6kYG14lEVG', '65ezkm2CfwVsYVhaymLrUB', '6BqdNDLZ3Pdcly46pu6nwj', '6IDh95GKLucPusCHJJvLLD', '6R15sXb3qRfJOsIbt1vS2a', '6iSpyAN4PjyCnxcJthU4Jl', '6iXBQXYVSMSY7LsZ7lj161', '6jF6iozvmHms55tWmsXMud', '6riYDJXW8ql7LTW4Wb9S7V', '6yH3xaGkj9OHFPCk7JiVPc', '71fp15098CPhaPyQ8t7ldo', '7dlNLDrE2Fc3IlvN5Ha8xa']\n"
     ]
    }
   ],
   "source": [
    "# 这个 cell 没用，草稿，我先试一下怎么获取训练的语料\n",
    "\n",
    "import sqlite3\n",
    "\n",
    "conn = sqlite3.connect('/Volumes/shared/murecom/intro/spotify/playlists.db')\n",
    "cp = conn.cursor()\n",
    "cp.execute(\"select id from playlists\")\n",
    "\n",
    "# pid = cp.fetchone()[0]\n",
    "# print(pid)\n",
    "cp.fetchone()\n",
    "\n",
    "ct = conn.cursor()\n",
    "# ct.execute(\"select track_id from playlist_tracks where playlist_id=?\", (pid,))\n",
    "# ct.fetchall()\n",
    "p = cp.fetchone()\n",
    "while p is not None:\n",
    "    pid = p[0]\n",
    "\n",
    "    ct.execute(\"select track_id from playlist_tracks where playlist_id=?\", (pid,))\n",
    "    # sentences.append(ct.fetchall())\n",
    "    tracks = ct.fetchall()\n",
    "    tracks = [t[0] for t in tracks]\n",
    "    print(len(tracks), tracks)\n",
    "\n",
    "    # next playlist\n",
    "    p = cp.fetchone()\n",
    "    break\n",
    "ct.close()\n",
    "cp.close()\n",
    "conn.close()"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "outputs": [],
   "source": [
    "import sqlite3\n",
    "\n",
    "\n",
    "def playlist_tracks_gen(db: str):\n",
    "    \"\"\"从数据库 db 中获取每张播放列表的曲目id\n",
    "\n",
    "    :return: 生成器，yield [tid, tid, ...] of a playlist\n",
    "    \"\"\"\n",
    "    conn = sqlite3.connect(db)\n",
    "    try:\n",
    "        cp = conn.cursor()\n",
    "        cp.execute(\"select id from playlists\")\n",
    "\n",
    "        p = cp.fetchone()\n",
    "        while p is not None:\n",
    "            pid = p[0]\n",
    "            # fetch tracks in playlist p\n",
    "            ct = conn.cursor()\n",
    "            ct.execute(\"select track_id from playlist_tracks where playlist_id=?\", (pid,))\n",
    "            tracks = ct.fetchall()\n",
    "            ct.close()\n",
    "\n",
    "            # [(\"\",), (\"id\",), (\"id\", ), ...] -> [\"id\", \"id\", ...]\n",
    "            tracks = [t[0] for t in tracks if t and t[0]]\n",
    "            yield tracks\n",
    "\n",
    "            # next playlist\n",
    "            p = cp.fetchone()\n",
    "        cp.close()\n",
    "    except:\n",
    "        raise\n",
    "    finally:\n",
    "        conn.close()\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "737 01JszWYuKqRjddPQ4creVF\n",
      "39 01apQz7E72krU1k1b4VWs7\n",
      "46 0A1hoCfMLkiAgvhWkkucJa\n",
      "73 0Hja9zlVQHC768PsPjWscW\n"
     ]
    }
   ],
   "source": [
    "# 试一下生成器\n",
    "sentences = playlist_tracks_gen(\"/Volumes/shared/murecom/intro/spotify/playlists.db\")\n",
    "\n",
    "i = 0\n",
    "for s in sentences:\n",
    "    print(len(s), s[0])\n",
    "    i += 1\n",
    "    if i > 3:\n",
    "        break"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "outputs": [],
   "source": [
    "class PlaylistTracksIter(object):\n",
    "    def __init__(self, db):\n",
    "        self.s = playlist_tracks_gen(db)\n",
    "\n",
    "    def __iter__(self):\n",
    "        yield from self.s\n",
    "\n",
    "\n",
    "DB = '/Volumes/shared/murecom/intro/spotify/playlists.db'"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "737 01JszWYuKqRjddPQ4creVF\n",
      "39 01apQz7E72krU1k1b4VWs7\n",
      "46 0A1hoCfMLkiAgvhWkkucJa\n",
      "73 0Hja9zlVQHC768PsPjWscW\n"
     ]
    }
   ],
   "source": [
    "# 试一下迭代器\n",
    "i = 0\n",
    "for s in PlaylistTracksIter(DB):\n",
    "    print(len(s), s[0])\n",
    "    i += 1\n",
    "    if i > 3:\n",
    "        break"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "outputs": [],
   "source": [
    "import gensim\n",
    "\n",
    "MODEL_FILE = '/Volumes/shared/murecom/intro/songs.word2vec'\n",
    "\n",
    "# Train a new model\n",
    "# model = gensim.models.Word2Vec(sentences=PlaylistTracksIter(DB), min_count=4)\n",
    "# with open(MODEL_FILE, \"wb\") as f:\n",
    "#     model.save(f)\n",
    "\n",
    "model = gensim.models.Word2Vec.load(MODEL_FILE)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "outputs": [
    {
     "data": {
      "text/plain": "array([ 4.5684148e-03,  5.2385400e-03, -7.7299788e-03,  1.5946460e-03,\n       -5.0252248e-03, -1.4793158e-03,  8.8905236e-03,  1.2116050e-03,\n        7.0763850e-03,  7.2929380e-04, -1.6901898e-03,  6.6553974e-03,\n        5.4897307e-03,  1.5793634e-03, -3.3323001e-03, -6.2783505e-03,\n       -6.6507314e-03, -8.8431053e-03,  1.3390756e-03,  1.3452291e-03,\n        6.2577580e-03,  6.3973619e-03, -3.6780667e-03,  5.4709911e-03,\n        7.5929998e-03, -6.0517122e-03,  5.0346851e-03, -7.9479171e-03,\n       -9.5174601e-03,  6.5671682e-04,  8.9104269e-03, -3.2153679e-03,\n        7.9768253e-03,  6.3682557e-03, -6.2449123e-03, -5.8733011e-03,\n        6.1626290e-03, -4.9687121e-03, -5.9139179e-03, -3.4214591e-03,\n       -6.5741013e-03, -1.9755459e-03, -3.9628460e-03, -6.6205263e-03,\n        3.4593535e-03,  2.0494533e-03,  2.8128552e-03,  3.9031242e-03,\n        1.0645962e-03, -5.6292294e-03,  5.2893758e-03,  2.8771926e-03,\n        4.9405717e-03,  2.3548030e-03, -7.6599433e-03,  6.3430406e-03,\n       -5.4602409e-03, -3.4972571e-03,  5.1552439e-03, -7.9456400e-03,\n       -2.8624821e-03, -6.3863541e-03,  8.4423497e-03,  6.6536069e-03,\n       -6.8117381e-04, -2.1556162e-03, -5.5787800e-04, -9.7631215e-04,\n       -1.0005307e-03, -5.7547353e-03,  2.8711963e-03, -3.0738354e-04,\n        2.0316385e-03,  1.8215823e-03,  8.0782482e-03,  7.4516726e-03,\n       -4.1890694e-03,  7.0840213e-03, -1.8576122e-03,  2.9229284e-03,\n       -8.9354273e-03, -8.9778902e-04,  1.2892532e-03, -6.2364722e-03,\n        9.1864110e-04,  1.0465169e-03,  4.4320226e-03,  2.6754308e-03,\n       -5.6872843e-04, -1.4809800e-03,  7.6653361e-03, -7.1179392e-03,\n        2.9271173e-03, -8.1002712e-05,  8.2369857e-03,  4.6627475e-03,\n       -1.0833836e-03, -2.9138708e-03, -1.4360308e-03, -1.1396479e-03],\n      dtype=float32)"
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model.wv['01JszWYuKqRjddPQ4creVF']"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "outputs": [
    {
     "data": {
      "text/plain": "39"
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model.wv.get_vecattr(\"01JszWYuKqRjddPQ4creVF\", \"count\")"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "outputs": [],
   "source": [
    "import sqlite3\n",
    "from operator import itemgetter\n",
    "\n",
    "conn = sqlite3.connect(DB)\n",
    "\n",
    "def find_artists(track_id: str) -> list:\n",
    "    ca = conn.cursor()  # get artists\n",
    "    ca.execute(\n",
    "        \"select a.name from artists a inner join track_artists ta on a.id = ta.artist_id where ta.track_id=?\",\n",
    "        (track_id,))\n",
    "    a = [a[0] for a in ca.fetchall()]\n",
    "    ca.close()\n",
    "    return a\n",
    "\n",
    "def find_song(song_name: str, limit=10):\n",
    "    c = conn.cursor()\n",
    "\n",
    "    # 用 FTS 优化了: https://www.sqlite.org/fts5.html\n",
    "    #   CREATE VIRTUAL TABLE tracks_name_fts USING fts5(name, id);\n",
    "    #   INSERT INTO tracks_name_fts SELECT name, id FROM tracks;\n",
    "    c.execute(f\"SELECT id, name FROM tracks_name_fts WHERE name MATCH '{song_name}' LIMIT {limit}\")\n",
    "\n",
    "    def tracks_id(t):\n",
    "        return t[0]\n",
    "    def tracks_name(t):\n",
    "        return t[1]\n",
    "\n",
    "    res = sorted((x + (model.wv.get_vecattr(tracks_id(x), \"count\"),)\n",
    "                  for x in c.fetchall() if tracks_id(x) in model.wv),\n",
    "                 key=itemgetter(-1), reverse=True)\n",
    "    res = [*res][:limit]\n",
    "\n",
    "    ca = conn.cursor()  # get artists\n",
    "    for i in range(len(res)):\n",
    "        tid = tracks_id(res[i])\n",
    "        a = find_artists(tid)\n",
    "        res[i] = list(res[i])\n",
    "        res[i].append(a)\n",
    "    ca.close()\n",
    "    c.close()\n",
    "\n",
    "    return [{\"id\": tracks_id(r), \"name\": tracks_name(r), \"artists\": r[-1], \"count\": r[-2]} for r in res]"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'id': '1Cj2vqUwlJVG27gJrun92y', 'name': 'The Sound of Silence', 'artists': ['Disturbed'], 'count': 486}\n",
      "{'id': '5y788ya4NvwhBznoDIcXwK', 'name': 'The Sound of Silence - Acoustic Version', 'artists': ['Simon & Garfunkel'], 'count': 340}\n",
      "{'id': '2LkaNhCrNVmcYgXJeLVmsw', 'name': 'The Sound of Silence', 'artists': ['Simon & Garfunkel'], 'count': 280}\n",
      "{'id': '0eZBeB2xFIS65jQHerispi', 'name': 'The Sound of Silence', 'artists': ['Disturbed'], 'count': 263}\n",
      "{'id': '64gpgh5jBMxyh7iVJll23t', 'name': 'The Sound of Silence', 'artists': ['Simon & Garfunkel'], 'count': 99}\n",
      "{'id': '2YplrdHMBoRdnHgMeHEwHm', 'name': 'The Sound of Silence - Electric Version', 'artists': ['Simon & Garfunkel'], 'count': 56}\n",
      "{'id': '0IHE30guMa90mZetZHVbuf', 'name': 'The Sound of Silence', 'artists': ['Joseph Sullinger'], 'count': 20}\n",
      "{'id': '5ye2aEP0ICWJgJCsawlCp3', 'name': 'The Sound of Silence - Overdubbed Version', 'artists': ['Simon & Garfunkel'], 'count': 6}\n",
      "{'id': '5N35prOM01qSay3vZyoTgU', 'name': 'É por você que canto - The Sound of Silence', 'artists': ['Leandro & Leonardo'], 'count': 4}\n"
     ]
    }
   ],
   "source": [
    "for t in find_song('the sound of silence'):\n",
    "    # print(t[4], t[5], t[-1], t[-2])  # id, name, artists, count_in_wv\n",
    "    print(t)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "outputs": [],
   "source": [
    "def suggest_songs(song_id):\n",
    "    similar = dict(model.wv.most_similar([song_id]))\n",
    "    song_ids = ', '.join((\"'%s'\" % x) for x in similar.keys())\n",
    "\n",
    "    c = conn.cursor()\n",
    "    c.execute(\"SELECT * FROM tracks WHERE id in (%s)\" % song_ids)\n",
    "\n",
    "    res = sorted((rec + (similar[rec[4]], find_artists(rec[4])) for rec in c.fetchall()),\n",
    "                 key=itemgetter(-1),\n",
    "                 reverse=True)\n",
    "    res = [*res]\n",
    "\n",
    "    return [{\"id\": r[4], \"name\": r[5], \"artists\": r[-1], \"similar\": r[-2]} for r in res]\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'id': '2NnrAdjE9cPdMklonMBuAv', 'name': 'willow - dancing witch version (Elvira remix)', 'artists': ['Taylor Swift', 'ELVIRA'], 'similar': 0.5026569962501526}\n",
      "{'id': '44dMahNEJeTOgOB26HdEcR', 'name': 'I Knew You Were Trouble.', 'artists': ['Taylor Swift'], 'similar': 0.4139394164085388}\n",
      "{'id': '4Z5AzZzTu01gzxZ7yCCO4C', 'name': 'Take One Step', 'artists': ['Tatiana Manaois'], 'similar': 0.41184818744659424}\n",
      "{'id': '06CRvgRb4fKQXpl2WPf2Cy', 'name': 'Meridian (Capo Song)', 'artists': ['TOPAZ'], 'similar': 0.4183271527290344}\n",
      "{'id': '4IePM62thd8OrAg8ELrYzO', 'name': 'Aléjate de Mi', 'artists': ['Sonido Profesional'], 'similar': 0.46160659193992615}\n",
      "{'id': '0qJeyYAgv6UpvewUxRXAhb', 'name': 'Rags2Riches 2 (feat. Lil Baby)', 'artists': ['Rod Wave', 'Lil Baby'], 'similar': 0.42182764410972595}\n",
      "{'id': '7FBMtFzffz4VIXyA9yAAwA', 'name': 'Hijo de la Luna', 'artists': ['Leo Rojas'], 'similar': 0.4233776926994324}\n",
      "{'id': '3TDaJHpLfApGdlRNEuNrD2', 'name': 'Ants Marching - Live at Piazza Napoleone, Lucca, Italy - July 2009', 'artists': ['Dave Matthews Band'], 'similar': 0.4144020676612854}\n",
      "{'id': '28jP25iq1PLryX3D7uVNM0', 'name': 'Outside Your Place', 'artists': ['DIVISION', 'Stirling', 'Despotem'], 'similar': 0.41890451312065125}\n",
      "{'id': '4SEEURVFejq4yoqyoBv3Ps', 'name': 'Little Girls - From the Annie (2014) Original Movie Soundtrack', 'artists': ['Cameron Diaz'], 'similar': 0.41987699270248413}\n"
     ]
    }
   ],
   "source": [
    "for t in suggest_songs('5y788ya4NvwhBznoDIcXwK'):\n",
    "    print(t)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "outputs": [],
   "source": [
    "def suggest_from(song_name: str):\n",
    "    s = find_song(song_name, limit=1)\n",
    "    return s + suggest_songs(s[0][\"id\"])"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "outputs": [
    {
     "data": {
      "text/plain": "[{'id': '0gplL1WMoJ6iYaPgMCL0gX',\n  'name': 'Easy On Me',\n  'artists': ['Adele'],\n  'count': 3156},\n {'id': '2PAoeEUqDSuhvzPv0Hr6yd',\n  'name': 'AFTERGLOW',\n  'artists': ['YTD', 'Sixthells'],\n  'similar': 0.46074774861335754},\n {'id': '10Nn7Qus3AwpOK5R2BuYLe',\n  'name': 'Insomnia Relief with Rain Sounds',\n  'artists': ['The Earbookers'],\n  'similar': 0.419079065322876},\n {'id': '6c9ZDwo8E81PpZGoWzc9VF',\n  'name': 'Horseplay',\n  'artists': ['Sada Baby'],\n  'similar': 0.4128553867340088},\n {'id': '3i7ZOuSmoKYSgLQuohMcig',\n  'name': 'Good Good Father',\n  'artists': ['Pat Barrett', 'Chris Tomlin'],\n  'similar': 0.42512083053588867},\n {'id': '20KXOKumUNxisRWv74hvUF',\n  'name': 'Celsius',\n  'artists': ['PNL'],\n  'similar': 0.4286656975746155},\n {'id': '4iNL0ZOUDAuxkKvE8mEY3p',\n  'name': \"Let's Talk\",\n  'artists': ['Josh Dally', 'Timecop1983'],\n  'similar': 0.4052392840385437},\n {'id': '5skQzF4pHBxhDogXslWN2X',\n  'name': 'Göran Soul Share',\n  'artists': ['Jaded Satire', 'Chill Select'],\n  'similar': 0.4151330292224884},\n {'id': '75TaaL8GNqoY7mxgz9TFB6',\n  'name': 'Stunt',\n  'artists': ['Darci'],\n  'similar': 0.4335898160934448},\n {'id': '2F3oPMRAUExFEJFWrqtqJV',\n  'name': 'Dra dit pepparn växer',\n  'artists': ['Casanovas'],\n  'similar': 0.4051080048084259},\n {'id': '1rPbnnDI0chsjw2WAwq7Qp',\n  'name': 'Heal Me - Spectrasoul Remix',\n  'artists': ['Arctic Lake', 'SpectraSoul'],\n  'similar': 0.44468972086906433}]"
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "suggest_from(\"easy on me\")"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "outputs": [
    {
     "data": {
      "text/plain": "[{'id': '10EGxvr4fSE42ABWZeJ3K3',\n  'name': 'Izzo (H.O.V.A.)',\n  'artists': ['JAY-Z'],\n  'count': 34},\n {'id': '56sAXFMfTagQGl5KOxvdxt',\n  'name': 'I Wanna Do It All',\n  'artists': ['Terri Clark'],\n  'similar': 0.421507328748703},\n {'id': '6UsZZfgK2QLinkxCsk4P2s',\n  'name': 'Kaputt wie ich',\n  'artists': ['Tarek K.I.Z'],\n  'similar': 0.43599334359169006},\n {'id': '7a7nlgfjoeEtIAW0QJzU4m',\n  'name': 'Nerve',\n  'artists': ['Soilwork'],\n  'similar': 0.4187915027141571},\n {'id': '1of4TwihFCtwaMSlgkFHLN',\n  'name': 'Soodamani',\n  'artists': ['Pop Shalini', 'Ranjith Govind'],\n  'similar': 0.4234713912010193},\n {'id': '6ayleuWDwuBXJ7LiTJiZnC',\n  'name': \"Walkin' in LA Freestyle\",\n  'artists': ['Lil Double 0'],\n  'similar': 0.42755126953125},\n {'id': '1T8YONUfkmHPqmUueSYq0V',\n  'name': 'Before Meaning Comes',\n  'artists': ['Ian William Craig'],\n  'similar': 0.4512949287891388},\n {'id': '5tQvGagX5oeTbPL6sXsiNy',\n  'name': 'Sugar',\n  'artists': ['Guitar Tribute Players'],\n  'similar': 0.4213887155056},\n {'id': '7ujaNHD8RzD6MFd7HIAthN',\n  'name': '157 - Im Zeichen der Schlangen - Teil 35',\n  'artists': ['Die drei ???'],\n  'similar': 0.4528729021549225},\n {'id': '1SGhreIdQO3v7z6SOgEEHC',\n  'name': 'Vibe for Me (Bob for Me)',\n  'artists': ['Aqyila'],\n  'similar': 0.42087820172309875},\n {'id': '1YnYbqTt94IWQK8DTTmIni',\n  'name': 'Stay X Chup Mahi',\n  'artists': ['Ajayz Kesbhat'],\n  'similar': 0.418727308511734}]"
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "suggest_from(\"Izzo\")"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "outputs": [
    {
     "data": {
      "text/plain": "[{'id': '4rc9kQ6qyssElIccFJgbJb',\n  'name': 'My Name Is',\n  'artists': ['Eminem'],\n  'count': 119},\n {'id': '3q0wgJXeUkhq2jeZ9JS7KN',\n  'name': \"I'm on Fire\",\n  'artists': [\"Whitey Morgan and the 78's\"],\n  'similar': 0.4211234450340271},\n {'id': '5XWplGAAmRPPGGbMpMnzy4',\n  'name': 'History - Live',\n  'artists': ['UPPERROOM'],\n  'similar': 0.445537805557251},\n {'id': '0rY0wiJbmpy42X0EUtgkd6',\n  'name': 'Oude Maasweg',\n  'artists': ['The Amazing Stroopwafels'],\n  'similar': 0.44175341725349426},\n {'id': '1Qw4FBX30bGdutJ19HBD7T',\n  'name': 'Lovefool (feat. Pia Mia)',\n  'artists': ['Pia Mia', 'twocolors'],\n  'similar': 0.4429745376110077},\n {'id': '38mpo90GPSUHgy2dUVvpZO',\n  'name': 'Maombi',\n  'artists': ['Nadia Mukami'],\n  'similar': 0.42666658759117126},\n {'id': '0H351Cn5b1uS4E4Cg1Jxb5',\n  'name': 'La Carta',\n  'artists': ['NAFTA'],\n  'similar': 0.43813273310661316},\n {'id': '3p0GBN1o2XyWsI7l6o3iGB',\n  'name': 'It\\'s Him (The Majestic Tale) [From \"Doctor Who - The Day of The Doctor\"]',\n  'artists': ['Murray Gold'],\n  'similar': 0.43847882747650146},\n {'id': '0AAl3LtvIhEilWXZmYHeh5',\n  'name': 'More',\n  'artists': ['Ken-Y', 'Jory Boy', 'Zion'],\n  'similar': 0.4319625794887543},\n {'id': '1dVbC0XoM4VxpDkrv1tcjf',\n  'name': 'Catching Fire',\n  'artists': ['Arjay Dang', 'Ryos'],\n  'similar': 0.4719669818878174},\n {'id': '3XyNeWiP6IogXUNdQLS6Qg',\n  'name': 'We Sleep Forever',\n  'artists': ['Aiden'],\n  'similar': 0.43374401330947876}]"
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "suggest_from(\"my name is\")"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "outputs": [
    {
     "data": {
      "text/plain": "[{'id': '0mD1a7haZKdX9I0oPywrMb',\n  'name': 'Air on a G String',\n  'artists': ['HAUSER',\n   'Johann Sebastian Bach',\n   'London Symphony Orchestra',\n   'Robert Ziegler'],\n  'count': 45},\n {'id': '2eIhmj1inaH2P4SYpgYZ78',\n  'name': 'Aynı Sokaklarda',\n  'artists': ['Şanışer'],\n  'similar': 0.4385406970977783},\n {'id': '2mhju5F4Hba8xX2udLVSaX',\n  'name': 'Trilogy',\n  'artists': ['Silent Planet'],\n  'similar': 0.4212125837802887},\n {'id': '0JUaqijY6i3hBzOdHGMP9j',\n  'name': 'Real Gone',\n  'artists': ['Sheryl Crow'],\n  'similar': 0.4512108266353607},\n {'id': '4fgJAlKZFuc8Nlq30fq8Tq',\n  'name': 'Eclypz',\n  'artists': ['Owl Vision'],\n  'similar': 0.4628591537475586},\n {'id': '6eXn9NxCovcNIQ8wXIIZv0',\n  'name': 'Jauh',\n  'artists': ['Nadya Fatira'],\n  'similar': 0.43133726716041565},\n {'id': '03KPztknFhsbbSbA0CSjbf',\n  'name': 'Go Tell It on the Mountain (Instrumental Version)',\n  'artists': ['Ivy Ravenwood'],\n  'similar': 0.41745278239250183},\n {'id': '1rU1OYNaz6h4BXKP0UB2A2',\n  'name': 'Hills',\n  'artists': ['Flipp Dinero'],\n  'similar': 0.4122016131877899},\n {'id': '4ybvIvKdvfkdsIYYAiaTiG',\n  'name': 'Got Your Back',\n  'artists': ['Empire'],\n  'similar': 0.41494008898735046},\n {'id': '0j1eAyEKHdn1EnKA0ZqX2v',\n  'name': 'F350 Freestyle',\n  'artists': ['David Morris'],\n  'similar': 0.4185600280761719},\n {'id': '7bYwm4LQaOsardfDdbVZg6',\n  'name': 'Six Etudes for Piano - q = 96',\n  'artists': ['Bruce Brubaker', 'Philip Glass'],\n  'similar': 0.4144984483718872}]"
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "suggest_from(\"air on G\")"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "outputs": [],
   "source": [
    "# conn.close()"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}